#!/bin/bash

IPS_USERS_PWDS="$1"
MY_BASTION_HOSTS="$2"

PLAY_HOME=$PLAY_HOME
echo "PLAY_HOME:$PLAY_HOME"

ip=$(ifconfig eth0 | grep "inet " | awk '{print $2}')
user=$(whoami)
this="${BASH_SOURCE-$0}"
system=$(cd -P -- "$(dirname -- "${this}")" >/dev/null && pwd -P)
reamin_target_hosts_path=${system}/reamin_target_hosts.cfg

source $system/shell_log.sh
source $system/progress_bar.sh
source $system/utils.sh

if [[ -n "${LOG_EXPECT_HOME}" ]]; then
  LOG_DIRECTORY="${LOG_EXPECT_HOME}/logs/expect"
else
  LOG_DIRECTORY="${system}/../logs/expect"
fi
# 如果目录不存在，则创建它
if [ ! -d "$LOG_DIRECTORY" ]; then
  mkdir -p "$LOG_DIRECTORY"
fi
LOG_FILE="${LOG_DIRECTORY}/stdout.$(date '+%Y-%m-%d').log"
LOG_FILE_PREFIX="\[$(date '+%Y-%m-%d\ %H:%M:%S.%3N')\ $ip\ $(whoami)\]开始expect交互:\n"

# 目标机器信息
#遍历主机列表
# 跳板机ip
BASTION_HOSTS=("$MY_BASTION_HOSTS")
# 已经配置完成的ip列表
REMAIN_TARGET_HOSTS=()
# 从配置获取要配置的ip列表
while read line;
do
    target_host=`echo $line | cut -d " " -f1`
    my_host_name=`echo $line | cut -d " " -f2`
    TARGET_HOSTS+=("$target_host")
    MY_HOST_NAME+=("$my_host_name")
done < $IPS_USERS_PWDS

# ADD_TARGET_HOSTS
# 第一次：就是TARGET_HOSTS
# 第二次：就是TARGET_HOSTS
# ALL_TARGET_HOSTS
# 第一次：就是INIT_HOSTS
# 第二次：就是TARGET_HOSTS+REMAIN_TARGET_HOSTS

# 后面新增的 1、进行用户及ssh-keygen创建
ADD_TARGET_HOSTS=("${TARGET_HOSTS[@]}")

# 检查文件路径是否有效
if [[ ! -s "$reamin_target_hosts_path" ]]; then
  log_info_new "第一次配置，无$reamin_target_hosts_path文件"
  # 第一次ip列表 全流程操作
  INIT_HOSTS=("${BASTION_HOSTS[@]}" "${ADD_TARGET_HOSTS[@]}")
  ADD_TARGET_HOSTS=("${INIT_HOSTS[@]}")
  # 目标为整体
  TMP_ALL_TARGET_HOSTS=("${INIT_HOSTS[@]}")
else
  # 把配置好的读出来
  log_info_new "有历史配置，读取$reamin_target_hosts_path文件"
  while read line;
  do
      _target_host=`echo $line | cut -d " " -f1`
      REMAIN_TARGET_HOSTS+=("$_target_host")
  done < $reamin_target_hosts_path
  # 剔除ADD_TARGET_HOSTS里在REMAIN_TARGET_HOSTS出现的元素
  ADD_TARGET_HOSTS=($(remove_elements_from_array ADD_TARGET_HOSTS[@] REMAIN_TARGET_HOSTS[@]))
  TMP_ALL_TARGET_HOSTS=("${REMAIN_TARGET_HOSTS[@]}" "${ADD_TARGET_HOSTS[@]}")
fi

# 调用函数并获取去重后的数组
ALL_TARGET_HOSTS=($(unique_array "${TMP_ALL_TARGET_HOSTS[@]}"))

for element in "${INIT_HOSTS[@]}"; do
    log_warn_new "#####INIT_HOSTS###"$element
done

for element in "${REMAIN_TARGET_HOSTS[@]}"; do
    log_warn_new "#####REMAIN_TARGET_HOSTS######"$element
done

for element in "${ADD_TARGET_HOSTS[@]}"; do
    log_warn_new "#####ADD_TARGET_HOSTS###"$element
done

for element in "${ALL_TARGET_HOSTS[@]}"; do
    log_warn_new "#####ALL_TARGET_HOSTS######"$element
done

TARGET_USER="ecs-user"
TARGET_KEY="/home/ecs-user/id_rsa"

# 新用户信息
NEW_USER="atguigu"
NEW_USER_PASSWORD="000000"

function get_my_host_name() {
    host=$1
    # 访问值
    for i in "${!TARGET_HOSTS[@]}"; do
        if [ "${TARGET_HOSTS[$i]}" == "$host" ]; then
            echo "${MY_HOST_NAME[$i]}"
        fi
    done
}

# 检查 expect 是否安装
check_expect() {
    if ! command -v expect &> /dev/null; then
        log_debug_new "expect could not be found, installing..."
        sudo yum update
        sudo yum install -y expect
        if [ $? -ne 0 ]; then
            log_error_new "Failed to install expect. Exiting."
            exit 1
        fi
    fi
    log_info_new "成功安装expect. Exiting."
}

# 使用 expect 生成 SSH 密钥对
generate_ssh_keys() {
    local host=$1
    local user=$2
    local password=$3

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn ssh $user@$host "ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa"
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "password:" {
        send "$password\n"
        exp_continue
    }
    "Overwrite (y/n)?" {
        send "y\n"
        exp_continue
    }
    "$user@*" {
        send "exit\n"
        expect eof
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "Failed to generate SSH keys on $host. "
        exit 1
    fi

    log_info_new "SSH keys generated successfully on $host."
}

# 使用 expect 配置 SSH 免密登录
configure_ssh_key() {
    local host1=$1
    local host2=$2
    local user=$3
    local password=$4

    expect <<EOF
set timeout 10
spawn ssh $user@$host1
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "password:" {
        send "$password\n"
        exp_continue
    }
    "$user@*" {
        send "sudo -u $user ssh-copy-id $user@$host2\n"
        sleep 2; # 添加延迟
        expect {
            "yes/no" {
                send "yes\n"
                exp_continue
            }
            "password:" {
                send "$password\n"
                exp_continue
            }
            "$user@*" {
                send_user "SSH key configured from $user@$host1 to $user@$host2.\n"
                send "exit\r"
                expect eof
            }
        }
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "Failed to configure SSH key from $user@$host1 to $user@$host2. "
        exit 1
    fi

    log_info_new "SSH key configured from $user@$host1 to $user@$host2."
}

# 使用 expect 登录并创建新用户
create_user() {
    local host=$1
    local target_user=$2
    local target_key=$3
    local new_user=$4
    local new_user_password=$5

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn sudo ssh -i $target_key $target_user@$host
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "$target_user@*" {
        # 终止所有使用该用户的进程
        send "sudo pkill -u $new_user\n"
        expect "$target_user@*"
        send "sudo groupdel $new_user || true\n"
        expect "$target_user@*"
        send "sudo userdel -r $new_user || true\n"
        expect "$target_user@*"
        send "sudo useradd -m -s /bin/bash $new_user\n"
        expect "$target_user@*"
        send "sudo echo \"$new_user:$new_user_password\" | sudo chpasswd\n"
        expect "$target_user@*"
        send "sudo usermod -aG wheel $new_user\n"
        expect "$target_user@*"
        # 配置 sudoers 文件以允许新用户免密 sudo
        send "echo '$new_user ALL=(ALL:ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/$new_user\n"
        expect "$target_user@*"
        send "sudo groupadd playgroundgroup\n"
        expect "$target_user@*"
        send "sudo usermod -aG playgroundgroup $new_user\n"
        expect "$target_user@*"
        send "sudo usermod -g playgroundgroup $new_user\n"
        expect "$target_user@*"
        send "sudo sed -i '/^#*PermitRootLogin/s/^#*PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config\n"
        expect "$target_user@*"
        send "sudo sed -i '/^#*PasswordAuthentication/s/^#*PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config\n"
        expect "$target_user@*"
        send "sudo systemctl restart sshd\n"
        expect "$target_user@*"
        send "exit\n"
        expect eof
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "Failed to create or recreate user $new_user on $host. "
        exit 1
    fi

    log_info_new "User $new_user created or recreated successfully on $host."
}

# 使用 expect 配置 SSH 允许新用户登录
configure_ssh() {
    local host=$1
    local target_user=$2
    local target_key=$3
    local new_user=$4

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn sudo ssh -i $target_key $target_user@$host
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "$target_user@*" {
        send "sudo sed -i '/^#*PermitRootLogin/s/^#*PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config\n"
        expect "$target_user@*"
        send "sudo sed -i '/^#*PasswordAuthentication/s/^#*PasswordAuthentication .*/PasswordAuthentication yes/' /etc/ssh/sshd_config\n"
        expect "$target_user@*"
        send "sudo systemctl restart sshd\n"
        expect "$target_user@*"
        send "exit\n"
        expect eof
    }
}
EOF

    if [ $? -ne 0 ]; then
        echo "Failed to configure SSH for $new_user on $host. "
        exit 1
    fi

    echo "SSH configured for $new_user on $host."
}

# 使用 ssh-keyscan 将其他机器加到信任名单里
add_to_known_hosts() {
    local host1=$1
    local host2=$2
    local user=$3
    local password=$4
    local new_user=$5
    local my_host_name=$(get_my_host_name "$host2")

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn ssh $user@$host1
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "password:" {
        send "$password\n"
        exp_continue
    }
    "$user@*" {
        # 删除已存在的条目
        send "sudo sed -i '/$my_host_name/d' /etc/hosts\n"
        expect "$user@*"
        # 添加新的条目
        send "echo '$host2 $my_host_name' | sudo tee -a /etc/hosts\n"
        expect "$user@*"
        send "sudo -u $new_user ssh-keyscan $host2 >> /home/$new_user/.ssh/known_hosts\n"
        expect {
            "yes/no" {
                send "yes\n"
                exp_continue
            }
            "$user@*" {
              send "sudo -u $new_user ssh-keyscan $my_host_name >> /home/$new_user/.ssh/known_hosts\n"
              expect {
                  "yes/no" {
                      send "yes\n"
                      exp_continue
                  }
                  "$user@*" {
                      send "exit\n"
                      expect eof
                  }
              }
            }
        }
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "Failed to add $host2 $my_host_name to known_hosts for $new_user on $host1. "
        exit 1
    fi

    log_info_new "$host2 $my_host_name added to known_hosts for $new_user on $host1."
}

# 确保权限设置正确
ensure_permissions() {
    local host=$1
    local user=$2
    local password=$3
    local new_user=$4

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn ssh $user@$host
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "password:" {
        send "$password\n"
        exp_continue
    }
    "$user@*" {
        send "sudo -u $new_user chmod 700 /home/$new_user/.ssh\n"
        expect "$user@*"
        send "sudo -u $new_user chmod 600 /home/$new_user/.ssh/id_rsa\n"
        expect "$user@*"
        send "sudo -u $new_user chmod 644 /home/$new_user/.ssh/id_rsa.pub\n"
        expect "$user@*"
        send "sudo -u $new_user echo '' | tee /home/$new_user/.ssh/known_hosts || true\n"
        expect "$user@*"
        send "sudo -u $new_user chmod 600 /home/$new_user/.ssh/known_hosts\n"
        expect "$user@*"
        send "sudo -u $new_user echo '' | tee /home/$new_user/.ssh/authorized_keys || true\n"
        expect "$user@*"
        send "sudo -u $new_user chmod 600 /home/$new_user/.ssh/authorized_keys\n"
        expect "$user@*"
        send "exit\n"
        expect eof
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "Failed to set permissions for $new_user on $host. "
        exit 1
    fi

    log_info_new "Permissions set successfully for $new_user on $host."
}

# 检查 SSH 免密登录
check_ssh_passwordless_login() {
    local host1=$1
    local host2=$2
    local new_user=$3
    local new_user_password=$4

    expect <<EOF
log_user 0
# -a 进行追加
log_file -a $LOG_FILE
# 打印当前时间
send_user $LOG_FILE_PREFIX
set timeout 10
spawn ssh $new_user@$host1 echo "SSH passwordless login successful from $host1 to $host2"
expect {
    "yes/no" {
        send "yes\n"
        exp_continue
    }
    "password:" {
        send "$new_user_password\n"
        exp_continue
    }
    "$new_user@*" {
        send "ssh $new_user@$host2\n"
        expect {
          "yes/no:" {
              send_user "将其他机器加到信任名单里失败\n"
              exit 1
          }
          "password:" {
              send_user "Password prompt detected. SSH passwordless login failed.\n"
              exit 1
          }
          "SSH passwordless login successful from $host1 to $host2" {
              send_user "SSH passwordless login successful from $host1 to $host2\n"
              exit 0
          }
          timeout {
              send_user "Timeout occurred. SSH passwordless login failed.\n"
              exit 1
          }
          eof {
              send_user "Unexpected EOF. SSH passwordless login failed.\n"
              exit 1
          }
        }
    }
}
EOF

    if [ $? -ne 0 ]; then
        log_error_new "\033[1;31m[ ✘ ] \033[0m Failed to check SSH passwordless login from $new_user@$host1 to $new_user@$host2."
        exit 1
    fi

    log_info_new "\033[1;32m[ √ ] \033[0m Successfully check SSH passwordless login from $new_user@$host1 to $new_user@$host2."
}

function print_progress() {
    draw_progress_bar $1 "$( date "+%r" )| $1 on $MAX"
    sleep 0.1
}

function ssh_no_pwd()
{
  # 进度条设置
  MAX=99
  # Make sure that the progress bar is cleaned up when user presses ctrl+c
  enable_trapping
  # Enable ETA
  ETA_ENABLED="true"
  # Create progress bar
  setup_scroll_area "Processing" $MAX
  print_progress 3

  log_info_new "\033[1;33m[ - ] \033[0m ssh 免密登录安装开始了..........................."

  log_step_one
  log_info_new "1、检查 expect 安装"

  check_expect
  print_progress 10

  log_step_two
  # 针对新增ip列表，遍历目标机器
  last_progress=0
  for ((i=0; i<${#ADD_TARGET_HOSTS[@]}; i++)); do
      HOST=${ADD_TARGET_HOSTS[$i]}
      log_info_new "2.$(($i+1))、开始安装 $HOST..."

      # 创建或重新创建新用户
      log_info_new "2.$(($i+1)).1、$HOST 创建或重新创建新用户，配置SSH允许新用户登录"
      create_user $HOST $TARGET_USER $TARGET_KEY $NEW_USER $NEW_USER_PASSWORD
      print_progress $((10+2+4*($i+1)))

      # 生成SSH密钥对
      log_info_new "2.$(($i+1)).2、$HOST 生成SSH密钥对"
      generate_ssh_keys $HOST $NEW_USER $NEW_USER_PASSWORD
      print_progress $((10+4+4*($i+1)))

      # 确保权限设置正确
      log_info_new "2.$(($i+1)).3、$HOST 确保权限设置正确，Ensuring permissions for $NEW_USER on $HOST..."
      ensure_permissions $HOST $NEW_USER $NEW_USER_PASSWORD $NEW_USER
      last_progress=$((10+6+4*($i+1)))
      print_progress $last_progress
  done

  log_step_three
  for ((m=0; m<${#ALL_TARGET_HOSTS[@]}; m++)); do
      HOST1=${ALL_TARGET_HOSTS[$m]}
      index=0
      for ((n=0; n<${#ALL_TARGET_HOSTS[@]}; n++)); do
          HOST2=${ALL_TARGET_HOSTS[$n]}
          # 如果两个ip不都在则配置
          if [ $(check_parameters_not_in_array "$HOST1" "$HOST2" "${REMAIN_TARGET_HOSTS[@]}") -ne 0 ]; then
              # 将其他机器加到信任名单里
              log_info_new "3.$(($m+1)).$(($index+1)).1、$HOST1->$HOST2 将其他机器加到信任名单里，Adding $HOST2 to known_hosts for $NEW_USER on $HOST1..."
              add_to_known_hosts $HOST1 $HOST2 $NEW_USER $NEW_USER_PASSWORD $NEW_USER
              print_progress $(($last_progress+2+8*($m+1)))

              # 配置新用户在这3台机器之间的SSH免密登录
              log_info_new "3.$(($m+1)).$(($index+1)).2、$HOST1->$HOST2 配置新用户在这3台机器之间的SSH免密登录，Configuring SSH key for $NEW_USER@$HOST1 to $NEW_USER@$HOST2..."
              configure_ssh_key $HOST1 $HOST2 $NEW_USER $NEW_USER_PASSWORD
              print_progress $(($last_progress+4+8*($m+1)))

              # 检查 SSH 免密登录
              log_info_new "3.$(($m+1)).$(($index+1)).3、$HOST1->$HOST2 检查 SSH 免密登录，Checking SSH passwordless login from $NEW_USER@$HOST1 to $NEW_USER@$HOST2..."
              check_ssh_passwordless_login $HOST1 $HOST2 $NEW_USER $NEW_USER_PASSWORD
              print_progress $(($last_progress+6+8*($m+1)))

              index=$index+1
          fi
      done
  done

  # 把安装成功的ip记录到文件中
  reamin_target_hosts "${ALL_TARGET_HOSTS[@]}" "$reamin_target_hosts_path"

  destroy_scroll_area
  log_sucess
  echo "All operations completed successfully."
}

ssh_no_pwd
